package cn.iocoder.yudao.module.vlog.comment.service;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.vlog.comment.bo.VLogCommentBO;
import cn.iocoder.yudao.module.vlog.comment.dal.dataobject.VLogCommentDO;
import cn.iocoder.yudao.module.vlog.comment.dal.dataobject.VLogCommentLikeDO;
import cn.iocoder.yudao.module.vlog.comment.dal.mysql.VLogCommentLikeMapper;
import cn.iocoder.yudao.module.vlog.comment.dal.mysql.VLogCommentMapper;
import cn.iocoder.yudao.module.vlog.comment.vo.AppVLogCommentCreateReqVO;
import cn.iocoder.yudao.module.vlog.comment.vo.AppVLogCommentPageReqVO;
import cn.iocoder.yudao.module.vlog.comment.vo.VLogCommentPageReqVO;
import cn.iocoder.yudao.module.vlog.info.dal.dataobject.VLogInfoDO;
import cn.iocoder.yudao.module.vlog.info.dal.mysql.VLogInfoMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.api.vlog.ErrorCodeConstants.*;

/**
 * 视频评论 Service 实现类
 *
 * @author 山野羡民（1032694760@qq.com）
 */
@Service
@Validated
public class VLogCommentServiceImpl implements VLogCommentService {

    @Resource
    private VLogCommentMapper commentMapper;
    @Resource
    private VLogCommentLikeMapper commentLikedMapper;
    @Resource
    private VLogInfoMapper vLogInfoMapper;

    @Override
    public Long createVLogComment(Long userId, AppVLogCommentCreateReqVO createReqVO) {
        VLogInfoDO vLogInfoDO = vLogInfoMapper.selectById(createReqVO.getVlogId());
        if (vLogInfoDO == null) {
            throw exception(INFO_NOT_EXISTS);
        }
        // 插入
        VLogCommentDO comment = BeanUtils.toBean(createReqVO, VLogCommentDO.class);
        comment.setShopId(vLogInfoDO.getShopId());
        comment.setUserId(userId);
        if (createReqVO.getParentId() != null && createReqVO.getParentId() > 0L) {
            // 提交了父级编号则说明是回复评论
            VLogCommentDO parentComment = ensureVLogCommentExists(createReqVO.getParentId());
            if (!Objects.equals(parentComment.getVlogId(), createReqVO.getVlogId())) {
                throw exception(COMMENT_PARENT_NOT_EXISTS);
            }
            comment.setParentId(parentComment.getId());
            comment.setToUserId(parentComment.getUserId());
        } else {
            // 非回复的评论才计入评论数
            vLogInfoDO.setCommentCount(vLogInfoDO.getCommentCount() + 1);
            vLogInfoMapper.updateById(vLogInfoDO);
        }
        commentMapper.insert(comment);
        // 返回
        return comment.getId();
    }

    @Override
    public VLogCommentDO getVLogComment(Long id) {
        return ensureVLogCommentExists(id);
    }

    @Override
    public void updateVLogCommentVisible(Long id, Boolean visible) {
        // 校验存在
        VLogCommentDO commentDO = ensureVLogCommentExists(id);
        commentDO.setVisible(visible);
        // 更新
        commentMapper.updateById(commentDO);
    }

    @Override
    public void deleteVLogComment(Long userId, Long id) {
        // 校验存在
        VLogCommentDO commentDO = ensureVLogCommentExists(id);
//        // 校验权限
//        permissionApi.checkWritePermission(userId, commentDO.getUserId());
        if (commentDO.getParentId() == null || commentDO.getParentId() <= 0L) {
            // 没有父级编号则说明不是回复得评论
            VLogInfoDO vLogInfoDO = vLogInfoMapper.selectById(commentDO.getVlogId());
            if (vLogInfoDO != null) {
                vLogInfoDO.setCommentCount(Math.max(0, vLogInfoDO.getCommentCount() - 1));
                vLogInfoMapper.updateById(vLogInfoDO);
            }
        }
        // 删除
        commentMapper.deleteById(id);
    }

    @Override
    public PageResult<VLogCommentBO> getVLogCommentPage(VLogCommentPageReqVO pageReqVO) {
        Page<VLogCommentBO> page = commentMapper.selectVLogCommentPage(
                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO.getShopId(), pageReqVO.getVlogId(), pageReqVO.getVisible());
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    @Override
    public PageResult<VLogCommentBO> getVLogCommentPage(AppVLogCommentPageReqVO pageReqVO) {
        Page<VLogCommentBO> page = commentMapper.selectVLogCommentPage(
                new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO.getShopId(), pageReqVO.getVlogId(), true);
        return new PageResult<>(page.getRecords(), page.getTotal());
    }

    @Override
    public List<VLogCommentBO> getVLogCommentListByParentId(List<Long> parentIds) {
        if (CollUtil.isEmpty(parentIds)) {
            return CollUtil.newArrayList();
        }
        List<VLogCommentBO> list = commentMapper.selectVLogCommentList(parentIds, true);
        if (CollUtil.isEmpty(list)) {
            list = CollUtil.newArrayList();
        }
        return list;
    }

    private VLogCommentDO ensureVLogCommentExists(Long id) {
        VLogCommentDO commentDO = commentMapper.selectById(id);
        if (commentDO == null) {
            throw exception(COMMENT_NOT_EXISTS);
        }
        return commentDO;
    }

    // ==================== 子表（视频评论点赞） ====================


    @Override
    public void likeVLogComment(Long userId, Long commentId) {
        //memberUserApi.ensureUserExists(userId);
        ensureVLogCommentExists(commentId);
        VLogCommentLikeDO likedDO = commentLikedMapper.selectOne(VLogCommentLikeDO::getUserId, userId,
                VLogCommentLikeDO::getCommentId, commentId);
        if (likedDO == null) {
            // 插入
            likedDO = new VLogCommentLikeDO();
            likedDO.setUserId(userId);
            likedDO.setVlogId(likedDO.getVlogId());
            likedDO.setCommentId(commentId);
            likedDO.setCanceled(false);
            commentLikedMapper.insert(likedDO);
        } else {
            likedDO.setCanceled(false);
            commentLikedMapper.updateById(likedDO);
        }
    }

    @Override
    public void unlikeVLogComment(Long userId, Long commentId) {
        //memberUserApi.ensureUserExists(userId);
        ensureVLogCommentExists(commentId);
        VLogCommentLikeDO likedDO = commentLikedMapper.selectOne(VLogCommentLikeDO::getUserId, userId,
                VLogCommentLikeDO::getCommentId, commentId);
        if (likedDO == null) {
            throw exception(COMMENT_LIKED_NOT_EXISTS);
        }
        likedDO.setCanceled(true);
        commentLikedMapper.updateById(likedDO);
    }

    @Override
    public Set<Long> getVLogCommentLikedUserIds(Long commentId) {
        List<VLogCommentLikeDO> list = commentLikedMapper.selectList(VLogCommentLikeDO::getCommentId, commentId,
                VLogCommentLikeDO::getCanceled, false);
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newHashSet();
        }
        return list.stream().map(VLogCommentLikeDO::getUserId).collect(Collectors.toSet());
    }

}
